﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using YArchitech.LIB;
using YArchitech.Revit;
using YJKCoordinate;
using YJKRGeometry;

namespace YJKOpeningDetail
{
	internal class CompoundComponent : Component
	{
		public void DimGapFunction(ElementInfo elementInfo, ViewPlan viewPlan, Dictionary<XYZ, DataWall> dicWallCurve, Dictionary<XYZ, List<Curve>> dicCombineGridCurve, Document doc)
		{
			this.m_doc = doc;
			Transaction transaction = new Transaction(this.m_doc, "Dim");
			try
			{
				transaction.Start();
				if (OpeningViewDataSetForm.BRadSelGrid)
				{
					this.CreateLocationDimensionByGridCurve(elementInfo, viewPlan, dicCombineGridCurve);
				}
				else
				{
					this.CreateLocationDimensionByWallCurve(elementInfo, viewPlan, dicWallCurve);
				}
				this.CreateLeaderDimension(elementInfo, viewPlan);
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
		}

		private void CreateLeaderDimension(ElementInfo elementInfo, ViewPlan viewPlan)
		{
			string strLevelText = null;
			string strFamText = null;
			Group drainGroup = elementInfo.element as Group;
			DrainBuryDataStruct drainBuryDataStruct = new DrainBuryDataStruct();
			DrainBuryData.ReadDataFromDrain("43FEE925-0EBE-45D8-BA6F-72A4411E065A", drainGroup, "DrainBuryData", out drainBuryDataStruct);
			Line line = null;
			this.GetDimText(elementInfo, ref strLevelText, ref strFamText, drainBuryDataStruct);
			string strStartLine = drainBuryDataStruct.m_strStartLine;
			DataSerializeDeserialize.StringToLine(this.m_doc, strStartLine, out line, true);
			XYZ endPoint = line.GetEndPoint(0);
			XYZ ptDimPosionFir = new XYZ(endPoint.X + NumbericTools.mmToFeet(800.0), endPoint.Y - NumbericTools.mmToFeet(400.0), endPoint.Z);
			base.LeaderDimension(endPoint, ptDimPosionFir, strFamText, strLevelText, viewPlan);
		}

		private bool CreateLocationDimensionByWallCurve(ElementInfo elementInfo, ViewPlan viewPlan, Dictionary<XYZ, DataWall> dicWallCurve)
		{
			Group group = elementInfo.element as Group;
			DrainBuryDataStruct drainBuryDataStruct = new DrainBuryDataStruct();
			DrainBuryData.ReadDataFromDrain("43FEE925-0EBE-45D8-BA6F-72A4411E065A", group, "DrainBuryData", out drainBuryDataStruct);
			XYZ ptFamilyGroup = new XYZ();
			List<string> lstLineString = drainBuryDataStruct.m_lstLineString;
			List<Curve> list = new List<Curve>();
			XYZ point = (group.Location as LocationPoint).Point;
			Line item = null;
			foreach (string lineString in lstLineString)
			{
				if (DataSerializeDeserialize.StringToLine(this.m_doc, lineString, out item, true))
				{
					list.Add(item);
				}
			}
			bool flag = DataSerializeDeserialize.StringToPoint(drainBuryDataStruct.m_strLocationPoint, out ptFamilyGroup);
			Transform transform = Transform.CreateTranslation(point - ptFamilyGroup);
			for (int i = 0; i < list.Count; i++)
			{
				list[i] = list[i].CreateTransformed(transform);
			}
			if (!flag)
			{
				return false;
			}
			if (elementInfo.revitLink != null)
			{
				Transform transform2 = elementInfo.revitLink.GetTransform();
				ptFamilyGroup = transform2.OfPoint(ptFamilyGroup);
				for (int j = 0; j < list.Count; j++)
				{
					list[j] = list[j].CreateTransformed(transform2);
				}
			}
			dicWallCurve = (from k in dicWallCurve
			orderby k.Key.DistanceTo(ptFamilyGroup)
			select k).ToDictionary((KeyValuePair<XYZ, DataWall> k) => k.Key, (KeyValuePair<XYZ, DataWall> k) => k.Value);
			if (dicWallCurve.Count > 0)
			{
				DataWall value = dicWallCurve.ElementAt(0).Value;
				XYZ key = dicWallCurve.ElementAt(0).Key;
				List<Curve> curveProjectPoint = PublicFunction.GetCurveProjectPoint(list, key);
				Curve curvrFirst = value.curvrFirst;
				Curve curveSecond = value.curveSecond;
				double dFirstWallWidth = value.dFirstWallWidth;
				double dSecondWallWidth = value.dSecondWallWidth;
				this.CreateDimensionByWallCurve(curvrFirst, dFirstWallWidth, curveSecond, curveProjectPoint, viewPlan);
				this.CreateDimensionByWallCurve(curveSecond, dSecondWallWidth, curvrFirst, curveProjectPoint, viewPlan);
				return true;
			}
			return false;
		}

		private bool CreateLocationDimensionByGridCurve(ElementInfo elementInfo, ViewPlan viewPlan, Dictionary<XYZ, List<Curve>> dicCombineGridCurve)
		{
			Group group = elementInfo.element as Group;
			DrainBuryDataStruct drainBuryDataStruct = new DrainBuryDataStruct();
			DrainBuryData.ReadDataFromDrain("43FEE925-0EBE-45D8-BA6F-72A4411E065A", group, "DrainBuryData", out drainBuryDataStruct);
			XYZ xyz = new XYZ();
			List<string> lstLineString = drainBuryDataStruct.m_lstLineString;
			List<Curve> list = new List<Curve>();
			XYZ nowLocationPoint = (group.Location as LocationPoint).Point;
			Line item = null;
			foreach (string lineString in lstLineString)
			{
				if (DataSerializeDeserialize.StringToLine(this.m_doc, lineString, out item, true))
				{
					list.Add(item);
				}
			}
			bool flag = DataSerializeDeserialize.StringToPoint(drainBuryDataStruct.m_strLocationPoint, out xyz);
			Transform transform = Transform.CreateTranslation(nowLocationPoint - xyz);
			for (int i = 0; i < list.Count; i++)
			{
				list[i] = list[i].CreateTransformed(transform);
			}
			if (!flag)
			{
				return false;
			}
			if (elementInfo.revitLink != null)
			{
				Transform transform2 = elementInfo.revitLink.GetTransform();
				xyz = transform2.OfPoint(xyz);
				for (int j = 0; j < list.Count; j++)
				{
					list[j] = list[j].CreateTransformed(transform2);
				}
			}
			dicCombineGridCurve = (from k in dicCombineGridCurve
			orderby k.Key.DistanceTo(nowLocationPoint)
			select k).ToDictionary((KeyValuePair<XYZ, List<Curve>> k) => k.Key, (KeyValuePair<XYZ, List<Curve>> k) => k.Value);
			if (dicCombineGridCurve.Count > 0)
			{
				XYZ key = dicCombineGridCurve.ElementAt(0).Key;
				List<Curve> value = dicCombineGridCurve.ElementAt(0).Value;
				List<XYZ> list2 = this.IsCurveIntersectGrid(value[0], list);
				List<XYZ> list3 = this.IsCurveIntersectGrid(value[1], list);
				bool flag2 = false;
				bool flag3 = false;
				if (list2 != null && list2.Count > 0)
				{
					flag2 = true;
				}
				if (list3 != null && list3.Count > 0)
				{
					flag3 = true;
				}
				if (!flag2 && !flag3)
				{
					this.CreateDimensionByGridCurve(value[0], value[1], list, viewPlan);
					this.CreateDimensionByGridCurve(value[1], value[0], list, viewPlan);
				}
				if ((flag2 && !flag3) || (!flag2 && flag3))
				{
					if (flag2)
					{
						this.CreateDimensionByGridCurve(value[0], value[1], list, viewPlan);
						this.CreateDimensionByIntersectGridCurve(value[0], value[1], list, viewPlan);
					}
					else
					{
						this.CreateDimensionByGridCurve(value[1], value[0], list, viewPlan);
						this.CreateDimensionByIntersectGridCurve(value[1], value[0], list, viewPlan);
					}
				}
				if (flag2 && flag3)
				{
					this.CreateDimensionByIntersectGridCurve(value[0], value[1], list, viewPlan);
					this.CreateDimensionByIntersectGridCurve(value[1], value[0], list, viewPlan);
				}
				return true;
			}
			return false;
		}

		private void GetDimText(ElementInfo elementInfo, ref string strLevelText, ref string strFamText, DrainBuryDataStruct drainBuryData)
		{
			string strGroup = drainBuryData.m_strGroup;
			double value = 0.0;
			string text = drainBuryData.m_strDeep;
			if (text.IsEmpty<char>())
			{
				text = Convert.ToInt32(value).ToString();
			}
			else
			{
				double value2 = NumbericTools.feetTomm(Convert.ToDouble(text));
				text = Convert.ToInt32(value2).ToString();
			}
			if (strGroup.Equals("0"))
			{
				strFamText = "排水沟";
				strLevelText = "深度" + text;
			}
			else if (strGroup.Equals("1"))
			{
				strFamText = "电缆沟";
				strLevelText = "深度" + text;
			}
			else
			{
				strFamText = "暖沟";
				strLevelText = "深度" + text;
			}
			this.DrawSlopDataInfo(elementInfo, drainBuryData);
		}

		private void CreateDimensionByWallCurve(Curve gridCurveFir, double dGridCuveFirWidth, Curve gridCurveSec, List<Curve> lstCompoundCurve, ViewPlan viewPlan)
		{
			YJKLine hyline = new YJKLine(gridCurveFir as Line);
			List<XYZ> list = new List<XYZ>();
			foreach (Curve curve in lstCompoundCurve)
			{
				Line otherLine = curve as Line;
				if (hyline.IsParallel(otherLine))
				{
					list.Add(curve.GetEndPoint(0));
					list.Add(curve.GetEndPoint(1));
				}
			}
			list = (from pt in list
			orderby gridCurveSec.Distance(pt) descending
			select pt).ToList<XYZ>();
			Line line = Line.CreateUnbound(list[0], (gridCurveSec as Line).Direction.Normalize());
			YJKLine hyline2 = new YJKLine(line);
			List<XYZ> list2 = new List<XYZ>();
			foreach (XYZ point in list)
			{
				XYZ project = hyline2.GetProject(point);
				if (!list2.Contains(project, new PointEqualComparer()))
				{
					list2.Add(project);
				}
			}
			list2 = (from pt in list2
			orderby gridCurveFir.Distance(pt)
			select pt).ToList<XYZ>();
			XYZ project2 = hyline.GetProject(list2[0]);
			XYZ xyz = list2[0].Subtract(project2).Normalize();
			XYZ xyz2 = project2.Add(xyz * 0.5 * dGridCuveFirWidth);
			XYZ vectorMove = (gridCurveFir as Line).Direction.Normalize();
			Line dimNewLine = Line.CreateBound(xyz2, list2[0]);
			base.CreateDetailLine(xyz2, list2[0], vectorMove, viewPlan, dimNewLine, false);
			for (int i = 0; i < list2.Count - 1; i++)
			{
				int index = i + 1;
				Line dimNewLine2 = Line.CreateBound(list2[i], list2[index]);
				base.CreateDetailLine(list2[i], list2[index], vectorMove, viewPlan, dimNewLine2, false);
			}
		}

		private void CreateDimensionByGridCurve(Curve gridCurveFir, Curve gridCurveSec, List<Curve> lstCompoundCurve, ViewPlan viewPlan)
		{
			YJKLine hyline = new YJKLine(gridCurveFir as Line);
			List<XYZ> list = new List<XYZ>();
			foreach (Curve curve in lstCompoundCurve)
			{
				Line otherLine = curve as Line;
				if (hyline.IsParallel(otherLine))
				{
					list.Add(curve.GetEndPoint(0));
					list.Add(curve.GetEndPoint(1));
				}
			}
			list = (from pt in list
			orderby gridCurveSec.Distance(pt) descending
			select pt).ToList<XYZ>();
			Line line = Line.CreateUnbound(list[0], (gridCurveSec as Line).Direction.Normalize());
			YJKLine hyline2 = new YJKLine(line);
			List<XYZ> list2 = new List<XYZ>();
			foreach (XYZ point in list)
			{
				XYZ project = hyline2.GetProject(point);
				if (!list2.Contains(project, new PointEqualComparer()))
				{
					list2.Add(project);
				}
			}
			list2 = (from pt in list2
			orderby gridCurveFir.Distance(pt)
			select pt).ToList<XYZ>();
			XYZ project2 = hyline.GetProject(list2[0]);
			XYZ vectorMove = (gridCurveFir as Line).Direction.Normalize();
			Line dimNewLine = Line.CreateBound(project2, list2[0]);
			base.CreateDetailLine(project2, list2[0], vectorMove, viewPlan, dimNewLine, false);
			for (int i = 0; i < list2.Count - 1; i++)
			{
				int index = i + 1;
				Line dimNewLine2 = Line.CreateBound(list2[i], list2[index]);
				base.CreateDetailLine(list2[i], list2[index], vectorMove, viewPlan, dimNewLine2, false);
			}
		}

		private void CreateDimensionByIntersectGridCurve(Curve gridCurveFir, Curve gridCurveSec, List<Curve> lstCompoundCurve, ViewPlan viewPlan)
		{
			YJKLine hyline = new YJKLine(gridCurveFir as Line);
			List<XYZ> lstPtParallelCurve = new List<XYZ>();
			foreach (Curve curve in lstCompoundCurve)
			{
				Line otherLine = curve as Line;
				if (hyline.IsParallel(otherLine))
				{
					lstPtParallelCurve.Add(curve.GetEndPoint(0));
					lstPtParallelCurve.Add(curve.GetEndPoint(1));
				}
			}
			List<XYZ> list = this.IsCurveIntersectGrid(gridCurveSec, lstCompoundCurve);
			if (list != null || list.Count > 0)
			{
				list.ForEach(delegate(XYZ pt)
				{
					lstPtParallelCurve.Add(pt);
				});
			}
			lstPtParallelCurve = (from pt in lstPtParallelCurve
			orderby gridCurveSec.Distance(pt) descending
			select pt).ToList<XYZ>();
			Line line = Line.CreateUnbound(lstPtParallelCurve[0], (gridCurveFir as Line).Direction.Normalize());
			YJKLine hyline2 = new YJKLine(line);
			List<XYZ> lstProjectOnLine = new List<XYZ>();
			foreach (XYZ point in lstPtParallelCurve)
			{
				XYZ project = hyline2.GetProject(point);
				if (!lstProjectOnLine.Contains(project, new PointEqualComparer()))
				{
					lstProjectOnLine.Add(project);
				}
			}
			XYZ vectorMove = (gridCurveSec as Line).Direction.Normalize();
			lstProjectOnLine = (from pt in lstProjectOnLine
			orderby gridCurveSec.Distance(pt) descending
			select pt).ToList<XYZ>();
			lstProjectOnLine = (from pt in lstProjectOnLine
			orderby lstProjectOnLine[0].DistanceTo(pt) descending
			select pt).ToList<XYZ>();
			for (int i = 0; i < lstProjectOnLine.Count - 1; i++)
			{
				int index = i + 1;
				Line dimNewLine = Line.CreateBound(lstProjectOnLine[i], lstProjectOnLine[index]);
				base.CreateDetailLine(lstProjectOnLine[i], lstProjectOnLine[index], vectorMove, viewPlan, dimNewLine, false);
			}
		}

		private List<XYZ> IsCurveIntersectGrid(Curve gridCurve, List<Curve> lstCurve)
		{
			List<XYZ> list = new List<XYZ>();
			YJKCurve hycurve = new YJKCurve(gridCurve);
			foreach (Curve otherCurve in lstCurve)
			{
				XYZ xyz = hycurve.IntersectionPoint(otherCurve);
				if (xyz != null)
				{
					list.Add(xyz);
				}
			}
			return list;
		}

		private void DrawSlopDataInfo(ElementInfo elementInfo, DrainBuryDataStruct drainBuryData)
		{
			List<SlopDataInfo> allSlopDataInfo = drainBuryData.GetAllSlopDataInfo();
			foreach (SlopDataInfo slopDataInfo in allSlopDataInfo)
			{
				XYZ thisLocation = slopDataInfo.ThisLocation;
				XYZ thisDriection = slopDataInfo.ThisDriection;
				double thisValue = slopDataInfo.ThisValue;
				SlopeTag slopeTag = new SlopeTag(this.m_doc, thisLocation, thisDriection, thisValue);
				slopeTag.DrawSlopeTag();
			}
		}

		private List<Document> m_lstDoc;
	}
}
